home *** CD-ROM | disk | FTP | other *** search
- Program search;
- {$A+,B-,D-,E+,F-,I+,L-,N-,O-,R-,S-,V-}
- {$M 16384,0,655360}
-
-
- { Copyright 1990 Trevor J Carlsen Version 1.05 24-07-90 }
- { This Program may be used and distributed as if it was in the Public Domain}
- { With the following exceptions: }
- { 1. if you alter it in any way, the copyright notice must not be }
- { changed. }
- { 2. if you use code excerpts in your own Programs, due credit must be }
- { given, along With a copyright notice - }
- { "Parts Copyright 1990 Trevor J Carlsen" }
- { 3. No Charge may be made For any Program using code from this Program.}
-
- { SEARCH will scan a File or group of Files and report on all occurrences }
- { of a particular String or group of Characters. if found the search String }
- { will be displayed along With the 79 Characters preceding it and the 79 }
- { Characters following the line it is in. Wild cards may be used in the }
- { Filenames to be searched. }
-
- { if you find this Program useful here is the author's contact address - }
-
- { Trevor J Carlsen }
- { PO Box 568 }
- { Port Hedland Western Australia 6721 }
- { Voice 61 [0]91 72 2026 }
- { Data 61 [0]91 72 2569 }
-
-
-
- Uses
- Dos,
- tpString, { Turbo Power's String handling library. Procedures and }
- { Functions used from this Unit are - }
- { BMSearch THESE ARE in THE SOURCE\MISC DIRECtoRY }
- { BMSearchUC }
- { BMMakeTable }
- { StUpCase }
- tctimer; { A little timing routine - not needed if lines (**) removed. }
-
- Const
- bufflen = 65000; { Do not increase this buffer size . Ok to decrease. }
- searchlen = bufflen;
- copyright1 = 'SEARCH - version 1.05 Copyright 1990 Trevor Carlsen';
- copyright2 = 'All rights reserved.';
-
- Type
- str79 = String[79];
- bufferType = Array[0..bufflen] of Byte;
- buffptr = ^bufferType;
-
- Const
- space = #32;
- quote = #34;
- comma = #44;
- CaseSensitive : Boolean = True; { default is a Case sensitive search }
- Var
- table : BTable; { Boyer-Moore search table }
- buffer : buffptr; { Pointer to new buffer }
- f : File;
- DisplayStr : Array[0..3] of str79;
- Filename,
- SrchStr : String;
- Slen : Byte Absolute SrchStr;
-
- Procedure Asc2Str(Var s, ns; max: Byte);
-
- { Converts an Array of asciiz Characters to a turbo String }
- { For speed the Variable st is effectively global and it is thereFore }
- { vitally important that max is no larger than the ns unTyped parameter }
- { Failure to ensure this can result in unpredictable Program behaviour }
-
- Var stArray : Array[0..255] of Byte Absolute s;
- st : String Absolute ns;
- len : Byte Absolute st;
-
- begin
- move(stArray[0],st[1],max);
- len := max;
- end; { Asc2Str }
-
- Procedure ReportError(e : Byte);
- { Displays a simple instruction screen in the event of insufficient }
- { parameters or certain other errors }
- begin
- Writeln('SYNTAX:');
- Writeln('SEARCH [-c] [path]Filename searchstr');
- Writeln(' eg: SEARCH c:\comm\telix\salt.doc "color"');
- Writeln(' or');
- Writeln(' SEARCH c:\comm\telix\salt.doc 13,10,13,10,13,10,13,10');
- Writeln(' or');
- Writeln(' SEARCH -c c:\*.* "MicroSoft"');
- Writeln;
- Writeln('if the -c option is used then a Case insensitive search is used.');
- Writeln('When used the -c option must be the first parameter.');
- halt(e);
- end; { ReportError }
-
- Procedure ParseCommandLine;
- { This Procedure is Really the key to everything as it parses the command }
- { line to determine what the String being searched For is. Because the }
- { wanted String can be entered in literal Form or in ascii codes this will }
- { disect and determine the method used. }
-
- Var
- parstr : String; { contains the command line }
- len : Byte Absolute parstr;{ will contain the length of cmd line }
- cpos, qpos,
- spos, chval : Byte;
- error : Integer;
-
- begin { ParseCommandLine}
- parstr := String(ptr(PrefixSeg,$80)^); { Get the command line }
- if parstr[1] = space then
- delete(parstr,1,1); { if the first Character is a space get rid of it }
- spos := pos(space,parstr); { find the first space }
- if spos = 0 then { No spaces which must be an error }
- ReportError(1);
-
- Filename := StUpCase(copy(parstr,1,spos-1)); { Filename used as a temp }
- if pos('-C',Filename) = 1 then begin { Case insensitive search required }
- CaseSensitive := False;
- delete(parstr,1,spos); { Get rid of the used portion }
- end; { if pos('-C' }
- spos := pos(space,parstr); { find next space }
- if spos = 0 then { No spaces which must be an error }
- ReportError(1);
- Filename := StUpCase(copy(parstr,1,spos-1)); { Get the File mask }
- delete(parstr,1,spos); { Get rid of the used portion }
-
- qpos := pos(quote,parstr); { look For the first quote Char }
- if qpos <> 0 then begin { quote Char found - so must be quoted Text }
- if parstr[1] <> quote then ReportError(2); { first Char must be quote }
- delete(parstr,1,1); { get rid of the first quote }
- qpos := pos(quote,parstr); { and find the next quote }
- if qpos = 0 then ReportError(3); { no more quotes - so it is an error }
- SrchStr := copy(parstr,1,qpos-1); { search String now defined }
- end { if qpos <> 0 }
-
- else begin { must be using ascii codes }
- Slen := 0;
- cpos := pos(comma,parstr); { find first comma }
- if cpos = 0 then cpos := succ(len);{ No comma - so only one ascii code }
- Repeat { create the search String }
- val(copy(parstr,1,pred(cpos)),chval,error);
- if error <> 0 then ReportError(7); { there is an error so bomb out }
- inc(Slen);
- SrchStr[Slen] := Char(chval); { add Char to the search String }
- delete(parstr,1,cpos); { get rid of used portion of parstr }
- cpos := pos(comma,parstr); { find the next comma }
- if cpos = 0 then cpos := succ(len); { no more commas so last Char }
- Until len = 0; { Until whole of command line is processed }
- end; { else}
-
- if not CaseSensitive then { change the Search String to upper Case }
- SrchStr := StUpCase(SrchStr);
- end; { ParseCommandLine }
-
- Function OpenFile(ofn : String): Boolean; { open a File For BlockRead/Write }
- Var
- error : Word;
- begin { OpenFile}
- assign(f,ofn);
- {$I-} reset(f,1); {$I+}
- error := Ioresult;
- if error <> 0 then
- Writeln('Cannot open ',ofn);
- OpenFile := error = 0;
- end; { OpenFile }
-
- Procedure CloseFile;
- begin
- {$I-}
- Close(f);
- if Ioresult <> 0 then; { don't worry too much if an error occurs here }
- {$I+}
- end; { CloseFile }
-
- Procedure SearchFile(Var Filename: String);
- { Reads a File into the buffer and then searches that buffer For the wanted}
- { String or Characters. }
- Var
- x,y,
- count,
- result,
- bufferpos : Word;
- abspos : LongInt;
- finished : Boolean;
-
- begin { SearchFile}
- BMMakeTable(SrchStr,table); { Create a Boyer-Moore search table }
- new(buffer); { make room on the heap For the buffers }
- {$I-} BlockRead(f,buffer^,searchlen,result); {$I+} { Fill buffer buffer }
- if Ioresult <> 0 then begin { error occurred While reading the File }
- CloseFile;
- ReportError(11);
- end; { if Ioresult }
- abspos := 0; { Initialise the Absolute File position marker }
- Repeat
- bufferpos := 0; { position marker in current buffer }
- count := 0; { offset from search starting point }
- finished := (result < searchlen); { if buffer <> full no more reads }
-
- Repeat { Do a BM search For search String }
- if CaseSensitive then { do a Case sensitive search }
- count:=BMSearch(buffer^[bufferpos],result-bufferpos,table,SrchStr)
- else { do a Case insensitive search }
- count:=BMSearchUC(buffer^[bufferpos],result-bufferpos,table,SrchStr);
-
- if count <> $FFFF then begin { search String found }
- inc(bufferpos,count); { starting point of SrchStr in buffer }
- DisplayStr[0] := HexL(abspos+bufferpos) + { hex and decimal pos }
- Form(' @######',(abspos+bufferpos) * 1.0);
- if bufferpos > 79 then { there is a line available beFore }
- Asc2Str(buffer^[bufferpos - 79],DisplayStr[1],79)
- else { no line available beFore the found }
- DisplayStr[1] := ''; { position so null the String }
- if (bufferpos + 79) < result then { at least 79 Chars can be }
- Asc2Str(buffer^[bufferpos],DisplayStr[2],79) { displayed }
- else { only display what is left in buffer }
- Asc2Str(buffer^[bufferpos],DisplayStr[2],result - bufferpos);
- if (bufferpos + 158) < result then { display the line following }
- Asc2Str(buffer^[bufferpos + 79],DisplayStr[3],79)
- else { no line following the found String }
- DisplayStr[3] := ''; { so null the display String }
- Writeln;
- Writeln(DisplayStr[0],' ',Filename);{ display the File locations }
-
- For x := 1 to 3 do begin
- For y := 1 to length(DisplayStr[x]) do{ filter out non-printables}
- if ord(DisplayStr[x][y]) < 32 then DisplayStr[x][y] := '.';
- if length(DisplayStr[x]) <> 0 then { only display Strings With }
- Writeln(DisplayStr[x]); { valid content }
- end; { For x }
-
- inc(bufferpos,Slen); { no need to check buffer in found st }
- end; { if count <> $ffff }
-
- Until (bufferpos >= (result-length(SrchStr))) or (count = $ffff);
-
- if not finished then begin { Fill 'er up again For another round }
- inc(abspos,result - Slen); { create overlap so no String missed }
- {$I-} seek(f,abspos);
- BlockRead(f,buffer^,searchlen,result); {$I+}
- if Ioresult <> 0 then begin
- CloseFile;
- ReportError(13);
- end;
- end; { if not finished}
- Until finished;
- dispose(buffer);
- end; { SearchFile }
-
- Procedure SearchForFiles;
- Var
- dirinfo : SearchRec;
- FullName: PathStr;
- DirName : DirStr;
- FName : NameStr;
- ExtName : ExtStr;
- found : Boolean;
- begin
- FindFirst(Filename,AnyFile,dirinfo);
- found := DosError = 0;
- if not found then begin
- Writeln('Cannot find ',Filename);
- ReportError(255);
- end;
- FSplit(Filename,DirName,FName,ExtName);
- While found do begin
- if (dirinfo.Attr and 24) = 0 then begin
- FullName := DirName + dirinfo.name;
- if OpenFile(FullName) then begin
- SearchFile(FullName);
- CloseFile;
- end;
- end;
- FindNext(dirinfo);
- found := DosError = 0;
- end;
- end; { SearchForFiles }
-
- begin { main}
- (**) StartTimer;
- Writeln(copyright1);
- Writeln(copyright2);
- ParseCommandLine;
- SearchForFiles;
- (**) WriteElapsedTime;
- end.
-